package com.cy.springcloudalibaba.services.impls;

import com.cy.springcloudalibaba.mappers.ProductMapper;
import com.cy.springcloudalibaba.models.Product;
import com.cy.springcloudalibaba.services.ProductService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @Description: 商品
 * @ClassName: ProductServiceImpl
 * @Author: chenyu
 * @Date: 2025/2/6 10:53
 */
@Slf4j
@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    private ProductMapper productMapper;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW) //开启新事务
    public Product reduceStock(Integer productId, Integer amount) throws Exception {
        log.info("[checkStock] 当前XID: {}", RootContext.getXID());
        //检查库存
        log.info("[checkStock] 检查 {} 库存", productId);
        Product product = productMapper.selectByPrimaryKey(productId);

        if (product.getStock() < amount) {
            log.warn("[checkStock] {} 库存不足，当前库存：{}", productId, product.getStock());
            throw new Exception("库存不足");
        }

        log.info("[reduceStock] 开始扣减 {} 库存", productId);
        //扣减库存
        int updateCount = productMapper.reduceStock(productId, amount);

        if (updateCount == 0) {
            log.warn("[reduceStock] 扣减 {} 库存失败", productId);
            throw new Exception("库存不足");
        }
        log.info("[reduceStock] 扣除 {} 库存成功", productId);

        return product;
    }

    /**
     * tcc服务（confirm）方法
     * @author chenyu
     * @param context 上下文
     * @return boolean
     * @date 2025/2/7 10:14
     */
    @Override
    public boolean commitTcc(BusinessActionContext context) {
        log.info("Confirm阶段，ProductServiceImpl，commitTcc --> xid = " + context.getXid() +
                "，commitTcc提交成功");
        return true;
    }

    /**
     * tcc服务（cancel）方法
     * @author chenyu
     * @param context 上下文
     * @return boolean
     * @date 2025/2/7 10:14
     */
    @Override
    public boolean cancelTcc(BusinessActionContext context) {
        log.info("Cancel阶段，ProductServiceImpl，cancelTcc --> xid = " + context.getXid() +
                "，cancelTcc提交失败");
        //TODO 这里可以实现中间件，非关系型数据库的回滚
        //进行数据库回滚
        Integer productId = (Integer) context.getActionContext("productId");
        Integer amount = (Integer) context.getActionContext("amount");

        //TODO 需要考虑幂等性问题，多线程下可能会多加
        productMapper.increaseStock(productId, amount);

        return true;
    }
}
